package com.googlecode.animator.view.timeline
{
	import com.googlecode.data.markers.GlobalMarkerVO;
	import com.googlecode.data.markers.HideMarkerVO;
	import com.googlecode.data.markers.KeyframeVO;
	
	import flash.display.DisplayObject;
	import flash.events.Event;
	import flash.ui.ContextMenu;
	import flash.ui.ContextMenuItem;
	
	import mx.containers.Canvas;
	import mx.core.UIComponent;
	
	import org.papervision3d.core.math.Number3D;

	/**
	 * The main component in the timeline assembly. 
	 * @author USER
	 * 
	 */
	public class TimelineGrid extends UIComponent
	{
		
		private var _grid:Grid;
		private var _thumb:Thumb;
		private var _gridNumSpacing:int;
		private var _tWidth:int;
		private var _vertOffset:int;
		private var _gridBox:Canvas;
		private var _keyframeListener:Canvas;
		
		/**
		 * Constructor. 
		 * 
		 */
		public function TimelineGrid()
		{
			super();
					
			_grid = new Grid();	
			_grid.makeGrid(_tWidth, 7, Timeline.SQUARE_WIDTH, _gridNumSpacing);		
			_grid.mouseEnabled = false;
			
			_thumb = new Thumb(Timeline.SQUARE_WIDTH, Timeline.SQUARE_WIDTH);
			_thumb.offsetY = 0;
			_thumb.y = 0;
			
			// permanent strip to receive right-clicks
			var paste:ContextMenuItem = new ContextMenuItem("Paste keyframe");
			//paste.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, onKeyFramePaste);
	
			var customContextMenu:ContextMenu = new ContextMenu();
			customContextMenu.hideBuiltInItems();
			customContextMenu.customItems.push(paste);
			
			_keyframeListener = new Canvas();
			_keyframeListener.height = Timeline.SQUARE_WIDTH;
			
			_keyframeListener.contextMenu = customContextMenu;
			
			addChild(_grid);
			addChild(_keyframeListener);
			addChild(_thumb);
			
			addEventListener(SnapDraggableObject.OBJECT_MOVE, onObjectMove);

		}
		
		/**
		 * Makes the visual elements of the timeline. 
		 * 
		 */
		public function makeTimeline():void
		{		
			_grid.makeGrid(_tWidth, 7, Timeline.SQUARE_WIDTH, _gridNumSpacing);

			_keyframeListener.width = _tWidth;
					
		}
		
		/**
		 * Ensures any object that subclasses SnapDraggableObject moves within bounds and the scrolling 
		 * of the timeline is adjusted automatically. 
		 * @param e
		 * 
		 */
		protected function onObjectMove(evt:Event):void
		{
			var marker:SnapDraggableObject = evt.target as SnapDraggableObject;
			
			// validate object
			if(marker == null)
			{
				return;
			}
			
			
			//If thumb has gone out of bounds, adjust scroller
			if((marker.x - _gridBox.horizontalScrollPosition + Timeline.SQUARE_WIDTH) > _gridBox.width)
			{
				_gridBox.horizontalScrollPosition += Timeline.SQUARE_WIDTH;
			}
			
			if(marker.x >= width)
			{
				marker.x = (Math.floor(width /Timeline.SQUARE_WIDTH) * Timeline.SQUARE_WIDTH) - Timeline.SQUARE_WIDTH;
				
				return;	
			}
			
			if(marker.x < _gridBox.horizontalScrollPosition + Timeline.SQUARE_WIDTH)
			{
				_gridBox.horizontalScrollPosition -= Timeline.SQUARE_WIDTH;
			}
				
			if(marker.x == 0)
			{
				_gridBox.horizontalScrollPosition = 0;	
			}
		
		}
		
		/////////////////////////////////////////////////////
		//
		// Generic marker functions
		//
		/////////////////////////////////////////////////////
		
		/**
		 * Removes all markers of the type specified. 
		 * 
		 */
		public function removeMarkers(type:Class):void
		{
			for(var i:uint=0; i<numChildren; i++)
			{
				if(getChildAt(i) is type)
				{
					(getChildAt(i) as SnapDraggableObject).cleanUp();
					removeChildAt(i);
					i--;
				}
			}
		}
		
		public function removeMarker(markerID:String):void
		{
			var marker:DisplayObject = getChildByName(markerID);
			
			(marker as SnapDraggableObject).cleanUp()
			/* if(marker is Keyframe)
			{
				(marker as Keyframe).cleanUp();
			}
			
			if(marker is SplitMarker)
			{
				(marker as SplitMarker).cleanUp();
			} */
			
			removeChild(marker);
		}
		
		/////////////////////////////////////////////////////
		//
		// Keyframe functions
		//
		/////////////////////////////////////////////////////
		
		/**
		 * Add a single keyframe. 
		 * @param kf
		 * 
		 */
		public function addKeyframe(kf:KeyframeVO):void
		{
			var keyframe:Keyframe = new Keyframe(_gridNumSpacing);
			
			keyframe.id = kf.id;
			keyframe.name = kf.id;
			keyframe.object3DName = kf.object3DName;
			keyframe.object3DPosition = kf.position;
			keyframe.time = kf.time;
			keyframe.offsetY = 50;
			keyframe.isDraggable = kf.isDraggable;
			
			addChild(keyframe);
		}
		
		/**
		 * Remove single keyframe. 
		 * @param keyframeID
		 * 
		 */
		public function removeKeyframe(keyframeID:String):void
		{
			var keyframe:DisplayObject = getChildByName(keyframeID);
			(keyframe as Keyframe).cleanUp();
			
			removeChild(keyframe);
		}
		
		public function updateKeyframePosition(name:String, pos:Number3D):void
		{
			if((getChildByName(name) as Keyframe) != null)
			{
				(getChildByName(name) as Keyframe).object3DPosition = pos;
				
			}		
		}
		
		
		
		/////////////////////////////////////////////////////
		//
		// Hide markers functions
		//
		/////////////////////////////////////////////////////
		
		
		/**
		 * Add a single hide marker.
		 * @param hm
		 * 
		 */
		public function addHideMarker(hm:HideMarkerVO):void
		{
			var hideMarker:SplitMarker = new SplitMarker(_gridNumSpacing, _gridNumSpacing);
			hideMarker.id = hm.id;
			hideMarker.name = hm.id;
			hideMarker.object3DName = hm.object3DName;
			hideMarker.begin = hm.begin;
			hideMarker.end = hm.end;
			hideMarker.offsetY = 70;
			
			addChild(hideMarker);
		}
		
		/**
		 * Remove single hide marker. 
		 * @param hideMarkerID
		 * 
		 */
		public function removeHideMarker(hideMarkerID:String):void
		{
			var hideMarker:DisplayObject = getChildByName(hideMarkerID);
			(hideMarker as SplitMarker).cleanUp();
			
			removeChild(hideMarker);
		}
		
		/////////////////////////////////////////////////////
		//
		// Global marker functions
		//
		/////////////////////////////////////////////////////
		
		public function addGlobalMarker(gm:GlobalMarkerVO):void
		{
			var globalMarker:GlobalMarker = new GlobalMarker(_gridNumSpacing);
			
			globalMarker.time = gm.time;
			globalMarker.id = gm.id;
			globalMarker.name = gm.id;
			globalMarker.offsetY = 20;
			
			addChild(globalMarker);
		}
		
		/////////////////////////////////////////////////////
		//
		// Flex overrides
		//
		/////////////////////////////////////////////////////
		
		override protected function commitProperties():void
		{
			super.commitProperties();
			
			_grid.y = _vertOffset;
			_keyframeListener.y = _vertOffset;
		}
		
		/////////////////////////////////////////////////////
		//
		// Getters and setters
		//
		/////////////////////////////////////////////////////
		
		/**
		 *  
		 * @param spacing
		 * 
		 */
		public function set gridNumSpacing(spacing:int):void
		{
			_gridNumSpacing = spacing;
		}
		
		public function get gridNumSpacing():int
		{
			return _gridNumSpacing;
		}
		
		public function set vertOffset(value:int):void
		{
			_vertOffset = value;
		}
		public function set tWidth(w:int):void
		{
			_tWidth = w;
		}
		
		public function set gridBox(gb:Canvas):void
		{
			_gridBox = gb
		}
		
		public function set thumbX(value:int):void
		{
			_thumb.x = value;
		}
	}
}